package com.jianganming.netty.chat;

import com.alibaba.fastjson.JSONObject;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.concurrent.GlobalEventExecutor;

public class ChatServer {

    public static void main(String[] args) {
        EventLoopGroup group1 = new NioEventLoopGroup(1);
        EventLoopGroup group2 = new NioEventLoopGroup();
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            ChannelFuture channelFuture = serverBootstrap.group(group1, group2)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            pipeline.addLast("decoder", new StringDecoder());
                            pipeline.addLast("encoder", new StringEncoder());
                            pipeline.addLast(new MyServerHandler());
                        }
                    }).bind(8887).sync();
            channelFuture.channel().closeFuture().sync();

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            group1.shutdownGracefully();
            group2.shutdownGracefully();
        }
    }
}

class MyServerHandler extends SimpleChannelInboundHandler<String>{
    //通道组  注意：必须是static
    private static ChannelGroup group = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    //将客户端通道组添加到group中
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name","[客户端]"+channel.remoteAddress());
        jsonObject.put("msg","上线了");
        group.writeAndFlush(jsonObject.toJSONString());
        group.add(channel);
    }

    //客户端离线，将客户端移除group
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name","[客户端]"+channel.remoteAddress());
        jsonObject.put("msg","下线了");
        group.writeAndFlush(jsonObject.toJSONString());

    }

    //服务端监控客户端上线
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println(ctx.channel().remoteAddress()+"上线了");
    }

    //服务端监控客户端下线
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println(ctx.channel().remoteAddress()+"下线了");
    }

    //服务端读取数据
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        //获取客户端通道
        Channel channel = ctx.channel();
        for (Channel channelClient : group) {
            if(channelClient !=channel){
                //将消息转发给客户端
                channelClient.writeAndFlush(msg);
            }
        }
    }

    //异常处理
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
        cause.printStackTrace();

    }
}
